package orm

import (
	"encoding/json"
	xml2 "gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/xml"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"strings"
)

type column[T any] []clause.Column

func NewClauses[T any](lenNum int) *column[T] {
	return new(column[T])
}

func (c *column[T]) AddColumnName(fieldName ...string) *column[T] {
	for _, s := range fieldName {
		*c = append(*c, clause.Column{Name: s})
	}
	return c
}

func (c *column[T]) Commit() []clause.Column {
	return *c
}

// 存在更新，不存在创建，只更新个别字段
func (c *column[T]) CreateUpdateStruct(db *gorm.DB, stru T, struMap map[string]interface{}) error {
	return db.Clauses(clause.OnConflict{
		Columns:   c.Commit(),
		DoUpdates: clause.Assignments(struMap),
	}).Create(&stru).Error
}

// 存在更新，不存在创建，更新非主键的所有字段
func (c *column[T]) CreateUpdateStructForUpdateOtherCol(db *gorm.DB, stru T) error {
	return db.Clauses(clause.OnConflict{
		Columns:   c.Commit(),
		UpdateAll: true,
	}).Create(&stru).Error
}

// 存在更新，不存在创建
func (c *column[T]) CreateUpdateStructByAllField(db *gorm.DB, stru T) error {
	struByte, _ := json.Marshal(stru)
	var struMap map[string]interface{}
	json.Unmarshal(struByte, &struMap)

	return c.CreateUpdateStruct(db, stru, struMap)
}

// 将 map 中的 key 全部转化成小写
func ConversionMapKeyToLower(struMap map[string]interface{}) map[string]interface{} {
	newStruMap := make(map[string]interface{}, len(struMap))
	for k, v := range struMap {
		switch v.(type) {
		case int, int8, int16, int32, int64, string, float64, float32:
		default:
			vByte, _ := json.Marshal(v)
			v = string(vByte)
		}
		newStruMap[strings.ToLower(k)] = v
	}
	return newStruMap
}

// 将 xml struct 中的 key 全部转化成小写
func ConversionMapKeyToLowerForXmlStru(stru interface{}) map[string]interface{} {
	struMap, _ := xml2.XmlUnmashal2Map(stru)
	return ConversionMapKeyToLower(struMap)
}

// 将 json struct 中的 key 全部转化成小写
func ConversionMapKeyToLowerForJsonStru(stru interface{}) map[string]interface{} {
	struByte, _ := json.Marshal(stru)
	var struMap map[string]interface{}
	json.Unmarshal(struByte, &struMap)
	return ConversionMapKeyToLower(struMap)
}
